﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Text.RegularExpressions;

public static partial class ExtensionMethods
{
    #region Extension for string
    /// <summary>
    /// Nâng hoa ký tự đầu tiên của một xâu
    /// </summary>
    public static string UppercaseFirstLetter(this string value)
    {
        if (!string.IsNullOrEmpty(value))
        {
            char[] array = value.ToCharArray();
            array[0] = char.ToUpper(array[0]);
            return new string(array);
        }
        return value;
    }
    /// <summary>
    /// Đếm số từ của một xâu
    /// </summary>
    public static int WordCount(this string value)
    {
        return value.Split(new char[] { ' ', '.', '?', ',', '!', ':' }, StringSplitOptions.RemoveEmptyEntries).Length;
    }
    /// <summary>
    /// Kiểm tra một xâu có phải là số hay không. Trả về true nếu là số, không thì ngược lại
    /// </summary>
    public static bool IsNumeric(this string value)
    {
        double output;
        return double.TryParse(value, out output);
    }
    /// <summary>
    /// Kiểm tra một xâu có phải là Email không
    /// </summary>
    public static bool IsEmail(this string value)
    {
        Regex reg = new Regex(@"^[a-z0-9_]+(?:\.[a-z0-9]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])$", RegexOptions.IgnoreCase);
        try
        {
            return reg.IsMatch(value);
        }
        catch
        {
            return false;
        }
    }
    /// <summary>
    /// Kiểm tra một xâu có phải là URL không
    /// </summary>
    public static bool IsURL(this string value)
    {
        Regex reg = new Regex(@"^(http|https|ftp)\://[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,3}(:[a-zA-Z0-9]*)?/?([a-zA-Z0-9\-\._\?\,\'/\\\+&%\$#\=~])*[^\.\,\)\(\s]$", RegexOptions.IgnoreCase);
        try
        {
            return reg.IsMatch(value);
        }
        catch
        {
            return false;
        }
    }
    /// <summary>
    /// Kiểm tra một xâu có phải là DateTime không
    /// </summary>
    public static bool IsDateTime(this string value)
    {
        DateTime dt;
        return DateTime.TryParse(value, out dt);
    }
    /// <summary>
    /// Kiểm tra một xâu có phải là số la mã không
    /// </summary>
    public static bool IsRomanNumber(this string value)
    {
       string[] soThuTuLaMa = {"I","II","III","IV","V","VI","VII","VIII","IX","X",
                                                 "XI","XII","XIII","XIV","XV","XVI","XVII","XVIII","XIX","XX",
                                                 "XXI","XXII","XXIII","XXIV","XXV","XXVI","XXVII","XXVIII","XXIX","XXX"};
       if (soThuTuLaMa.Contains(value)) return true;
       return false;
    }
    /// <summary>
    /// Chuẩn hóa một xâu
    /// </summary>
    public static string ToNormalString(this string value)
    {
        StringBuilder retValue = new StringBuilder(string.Empty);
        if (!string.IsNullOrEmpty(value))
        {
            string[] array = value.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
            foreach (string item in array)
            {
                retValue.Append(item + " ");
            }
        }
        return retValue.ToString().TrimEnd();
    }
    /// <summary>
    /// Chuẩn hóa 1 số điện thoại (ví dụ: 841682821740)
    /// </summary>
    public static string ToNormalPhoneNumber(this string value)
    {
        string normalPhoneNumber = string.Empty;
        foreach (char item in value)
        {
            if (item >= '0' && item <= '9')
                normalPhoneNumber += item;
        }
        //Kiểm tra 2 ký tự đầu, nếu không phải là 84 thì xử lý
        if (!normalPhoneNumber.StartsWith("84"))
        {
            //Kiểm tra 1 ký tự đầu, nếu là ký tự 0 thì cắt đi
            if (normalPhoneNumber.StartsWith("0"))
            {
                normalPhoneNumber = normalPhoneNumber.Substring(1);
            }
            //Thêm ký tự 84 vào trước
            normalPhoneNumber = "84" + normalPhoneNumber;
        }
        return normalPhoneNumber;
    }
    /// <summary>
    /// Chuyển một xâu tiếng Việt có dấu thành không dấu (Nguồn: internet)
    /// </summary>
    public static string ToVietnameseWithoutAccent(this string text)
    {
        if (!string.IsNullOrEmpty(text))
        {
            System.Text.RegularExpressions.Regex regex = new System.Text.RegularExpressions.Regex(@"\p{IsCombiningDiacriticalMarks}+");
            string strFormD = text.Normalize(System.Text.NormalizationForm.FormD);
            return regex.Replace(strFormD, String.Empty).Replace('\u0111', 'd').Replace('\u0110', 'D');
        }
        return text;
    }
    /// <summary>
    /// Mã hóa MD5
    /// </summary>
    public static string ToMD5UTF8Encryption(this string value)
    {
        Byte[] originalBytes;
        Byte[] encodedBytes;
        MD5 md5 = new MD5CryptoServiceProvider();
        originalBytes = UTF8Encoding.Default.GetBytes(value);
        encodedBytes = md5.ComputeHash(originalBytes);
        //Convert encoded bytes back to a 'readable' string
        return BitConverter.ToString(encodedBytes);
    }

    /// <summary>
    /// Mã hóa dữ liệu theo RSA
    /// </summary>
    /// <param name="_dataEncrypt">Dữ liệu cần mã hóa</param>
    /// <returns>Dữ liệu đã mã hóa</returns>
    public static string ToRsaEncrypt(this string value, string publicKeyPath)
    {
        RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider();
        using (System.IO.StreamReader reader = new System.IO.StreamReader(publicKeyPath))
        {
            string publicOnlyKeyXML = reader.ReadToEnd();
            rsa.FromXmlString(publicOnlyKeyXML);
            reader.Close();
        }
        //read plaintext, encrypt it to ciphertext

        byte[] plainbytes = System.Text.Encoding.UTF8.GetBytes(value);
        byte[] cipherbytes = rsa.Encrypt(plainbytes, false);
        return Convert.ToBase64String(cipherbytes);
    }

    /// <summary>
    /// Giải mã dữ liệu theo RSA
    /// </summary>
    /// <param name="_dataDecrypt"></param>
    /// <returns></returns>
    public static string ToRsaDecrypt(this string value, string privateKeyPath)
    {
        RSACryptoServiceProvider rsa = CreateRSACryptoServiceProvider();
        byte[] cipherbytes = Convert.FromBase64String(value);
        using (System.IO.StreamReader reader = new System.IO.StreamReader(privateKeyPath))
        {
            string publicPrivateKeyXML = reader.ReadToEnd();
            rsa.FromXmlString(publicPrivateKeyXML);
            reader.Close();
        }
        //read ciphertext, decrypt it to plaintext
        byte[] plain = rsa.Decrypt(cipherbytes, false);
        return System.Text.Encoding.UTF8.GetString(plain);

    }

    /// <summary>
    /// Tạo đối tượng RSACryptoServiceProvider
    /// </summary>
    /// <returns></returns>
    private static RSACryptoServiceProvider CreateRSACryptoServiceProvider()
    {
        CspParameters cspParams = new CspParameters(1, "VTCOnlinePassContainerKey");
        cspParams.Flags = CspProviderFlags.UseUserProtectedKey;
        cspParams.ProviderName = "Microsoft Strong Cryptographic Provider";
        return new RSACryptoServiceProvider(cspParams);
    }
    #endregion

    #region Extension for decimal
    public static decimal Round(this decimal value)
    {
        return Math.Round(value, MidpointRounding.AwayFromZero);
    }
    #endregion
    #region Extension for DateTime
    /// <summary>
    /// Lấy ngày đầu tiên của tháng
    /// </summary>
    public static DateTime GetFirstDayOfMonth(this DateTime value)
    {
        return new DateTime(value.Year, value.Month, 1, 0, 0, 0);
    }
    /// <summary>
    /// Lấy ngày cuối cùng của tháng
    /// </summary>
    public static DateTime GetLastDayOfMonth(this DateTime value)
    {
        return value.GetFirstDayOfMonth().AddMonths(1).AddSeconds(-1);
    }

    /// <summary>
    /// Cộng ngày tháng với quy ước 1 tháng có 30 ngày
    /// </summary>
    /// <param name="values">Số ngày cần cộng thêm</param>
    /// <returns></returns>
    public static DateTime AddDaysRound30(this DateTime d, int values)
    {
        int months = (values - 1) / 30;
        int days = (values - 1) % 30;
        DateTime retValue = d.AddMonths(months);
        if (retValue.Day + days <= new DateTime(retValue.Year, retValue.Month, 1).AddMonths(1).AddDays(-1).Day)
        {
            retValue = retValue.AddDays(days);
        }
        else
        {
            days = retValue.Day + days - 30;
            retValue = new DateTime(retValue.Year, retValue.Month + 1, days);
        }
        return retValue;
    }

    /// <summary>
    /// Trả về số ngày của tháng với quy ước một tháng có 30 ngày.
    /// </summary>
    public static int GetDayRound30(this DateTime d)
    {
        DateTime tmp = new DateTime(d.Year, d.Month, 1, 0, 0, 0);
        tmp = tmp.AddMonths(1).AddDays(-1);
        if (tmp.Day == d.Day) return 30;
        return d.Day;
    }
    #endregion


}

